package com.minimalist.lindi.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Assert;
import cn.hutool.http.HttpStatus;
import com.minimalist.common.config.exception.BusinessException;
import com.minimalist.common.config.mybatis.bo.PageResp;
import com.minimalist.common.entity.basic.vo.file.FileVO;
import com.minimalist.common.entity.lindi.po.LindiTradeApplicationInvoice;
import com.minimalist.common.entity.lindi.vo.tradeapplicationinvoice.LindiTradeApplicationInvoiceQueryVO;
import com.minimalist.common.entity.lindi.vo.tradeapplicationinvoice.LindiTradeApplicationInvoiceVO;
import com.minimalist.common.feign.client.basic.FileFeignClient;
import com.minimalist.common.response.R;
import com.minimalist.common.utils.UnqIdUtil;
import com.minimalist.lindi.mapper.LindiTradeApplicationInvoiceMapper;
import com.minimalist.lindi.service.LindiTradeApplicationInvoiceService;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 林地指标交易平台_交易申请发票 服务层实现。
 *
 * @author 11987
 * @since 2025-06-04
 */
@Service
public class LindiTradeApplicationInvoiceServiceImpl extends ServiceImpl<LindiTradeApplicationInvoiceMapper, LindiTradeApplicationInvoice> implements LindiTradeApplicationInvoiceService{
    private static final Logger log = LoggerFactory.getLogger(LindiTradeApplicationInvoiceServiceImpl.class);


    @Autowired
    private LindiTradeApplicationInvoiceMapper mapper;

    @Autowired
    private FileFeignClient fileFeignClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addTradeApplicationInvoice(
            LindiTradeApplicationInvoiceVO tradeApplicationInvoiceVO){
        LindiTradeApplicationInvoice record = BeanUtil.copyProperties(
                tradeApplicationInvoiceVO,
                LindiTradeApplicationInvoice.class);
        record.setInvoiceId(UnqIdUtil.uniqueId());
        int insert = mapper.insert(record, true);
        Assert.isTrue(insert == 1, () -> new BusinessException("添加交易申请发票失败"));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteTradeApplicationInvoiceByTradeApplicationInvoiceId(
            Long tradeApplicationInvoiceId){
        LindiTradeApplicationInvoice record = mapper
                .selectTradeApplicationInvoiceByTradeApplicationInvoiceId(
                        tradeApplicationInvoiceId);
        Assert.notNull(record, () -> new BusinessException("交易申请发票不存在"));
        int delete = mapper.delete(record);
        Assert.isTrue(delete == 1, () -> new BusinessException("删除交易申请发票失败"));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTradeApplicationInvoiceByTradeApplicationInvoiceId(
            LindiTradeApplicationInvoiceVO tradeApplicationInvoiceVO){
        LindiTradeApplicationInvoice record = mapper
                .selectTradeApplicationInvoiceByTradeApplicationInvoiceId(tradeApplicationInvoiceVO
                        .getInvoiceId());
        Assert.notNull(record, () -> new BusinessException("交易申请发票不存在"));
        BeanUtil.copyProperties(tradeApplicationInvoiceVO, record,
                CopyOptions.create().ignoreNullValue());
        int update = mapper.update(record);
        Assert.isTrue(update == 1, () -> new BusinessException("更新交易申请发票失败"));
    }

    @Override
    public PageResp<LindiTradeApplicationInvoiceVO> getPageTradeApplicationInvoiceList(
            LindiTradeApplicationInvoiceQueryVO queryVO){
        Page<LindiTradeApplicationInvoice> page = mapper
                .selectPageTradeApplicationInvoiceList(queryVO);
        List<LindiTradeApplicationInvoiceVO> voList = BeanUtil.copyToList(
                page.getRecords(),
                LindiTradeApplicationInvoiceVO.class);
        return new PageResp<>(voList, voList.size());
    }

    @Override
    public LindiTradeApplicationInvoiceVO
    getTradeApplicationInvoiceByTradeApplicationInvoiceId(
            Long tradeApplicationInvoiceId){
        LindiTradeApplicationInvoice record = mapper
                .selectTradeApplicationInvoiceByTradeApplicationInvoiceId(
                        tradeApplicationInvoiceId);
        Assert.notNull(record, () -> new BusinessException("交易申请发票不存在"));
        if (record.getInvoiceFileId() != null){
            R<FileVO> result = fileFeignClient.getFileByFileId(record.getInvoiceFileId());
            Assert.isTrue(result.getCode() == HttpStatus.HTTP_OK && result.getData() != null
                    , () -> new BusinessException("获取发票文件失败"));
        }
        return BeanUtil.copyProperties(record, LindiTradeApplicationInvoiceVO.class);
    }

    @Override
    public List<LindiTradeApplicationInvoiceVO> getTradeApplicationInvoiceListByTradeApplicationId(
            Long tradeApplicationId){
        // 查询所有数据
        List<LindiTradeApplicationInvoice> result
                = mapper.selectTradeApplicationInvoiceListByTradeApplicationId(
                tradeApplicationId);

        // 转换为VO
        List<LindiTradeApplicationInvoiceVO> lindiTradeApplicationInvoiceVOList
                = BeanUtil.copyToList(result, LindiTradeApplicationInvoiceVO.class);

        // 批量获取文件信息
        List<Long> fileIds = lindiTradeApplicationInvoiceVOList.stream()
                .map(LindiTradeApplicationInvoiceVO::getInvoiceFileId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        if (!fileIds.isEmpty()){
            try{
                R<List<FileVO>> fileResult = fileFeignClient.getFileListByFileIds(fileIds);
                if (fileResult.getCode() == HttpStatus.HTTP_OK && fileResult.getData() != null){
                    List<FileVO> fileList = fileResult.getData();
                    // 将文件信息设置到对应的VO中
                    lindiTradeApplicationInvoiceVOList.forEach(vo -> {
                        if (vo.getInvoiceFileId() != null){
                            fileList.stream()
                                    .filter(file -> vo.getInvoiceFileId()
                                            .equals(file.getFileId()))
                                    .findFirst()
                                    .ifPresent(vo::setInvoiceFile);
                        }
                    });
                }
            } catch (Exception e){
                // 批量获取文件失败时记录日志，但不影响整体查询
                // 可以考虑添加日志记录
                log.warn("批量获取发票文件失败，发票ID列表: {}", fileIds, e);
            }
        }

        return lindiTradeApplicationInvoiceVOList;
    }
}

